/*
 * $Header: /opt/javacvs/bk/src/main/java/com/uusee/framework/util/query/CriteriaUtilForHibernate.java,v 1.1 2009/04/02 10:08:52 wangrui Exp $
 * $Revision: 1.1 $
 * $Date: 2009/04/02 10:08:52 $
 * ============================================================================
 *
 * Copyright (c) 2008 Beijing uusee Tech CO.,  All rights reserved.
 *
 * ============================================================================
 */
package com.uusee.framework.util.query;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

/**
 * 
 * 
 * @author <a href="mailto:du_yi@bbn.cn">duyi</a>
 * 
 * Create Time: 2008-3-27 下午03:31:14
 */
public class CriteriaUtilForHibernate {
	public static Criteria fillCriteria(Criteria criteria, CriteriaInfo cInfo, boolean isGetCount) {
		if (cInfo != null) {
			if (cInfo.getFilters() != null && cInfo.getFilters().size() > 0) {
				for (Filter filter : cInfo.getFilters()) {
					criteria.add(buildCriterion(filter));
				}
			}
		}
		
		if (isGetCount) {
			criteria.setProjection(Projections.rowCount());
		} else if (cInfo != null) {
			if (cInfo.getSorts() != null && cInfo.getSorts().size() > 0) {
				for (Sort sort : cInfo.getSorts()) {
					addOrder(criteria, sort.getProperty(), sort.getOrder());
				}
			}
			if (cInfo.isOffset() && cInfo.getFirstResult() >= 0 && cInfo.getMaxResult() > 0) {
				criteria.setFirstResult(cInfo.getFirstResult());
				criteria.setMaxResults(cInfo.getMaxResult());
			}
		}
		return criteria;
	}

	private static Criterion buildCriterion(Filter filter) {
		Criterion criterion = null;
		
		int operator = filter.getOperator();
		String propertyName = filter.getPropertyName();
		String otherPropertyName = filter.getOtherPropertyName();
		Object value = filter.getValue();
		Object lowValue = filter.getLowValue();
		Object highValue = filter.getHighValue();
		Map propertyNameValues = filter.getPropertyNameValues();
		Collection collectionValues = filter.getCollectionValues();
		Object[] objectValues = filter.getObjectValues();
		Filter logicCondition = filter.getLogicCondition();
		Filter otherLogicCondition = filter.getOtherLogicCondition();
		
		switch (operator) {
		case Filter.ALL_EQ:
			criterion = Restrictions.allEq(propertyNameValues);
			break;
		case Filter.ID_EQ:
			criterion = Restrictions.idEq(value);
			break;
		case Filter.EQ:
			criterion = Restrictions.eq(propertyName, value);
			break;
		case Filter.NE:
			criterion = Restrictions.ne(propertyName, value);
			break;
		case Filter.GE:
			criterion = Restrictions.ge(propertyName, value);
			break;
		case Filter.GT:
			criterion = Restrictions.gt(propertyName, value);
			break;
		case Filter.LE:
			criterion = Restrictions.le(propertyName, value);
			break;
		case Filter.LT:
			criterion = Restrictions.lt(propertyName, value);
			break;
		case Filter.EQ_PROPERTY:
			criterion = Restrictions.eqProperty(propertyName, otherPropertyName);
			break;
		case Filter.NE_PROPERTY:
			criterion = Restrictions.neProperty(propertyName, otherPropertyName);
			break;
		case Filter.GE_PROPERTY:
			criterion = Restrictions.geProperty(propertyName, otherPropertyName);
			break;
		case Filter.GT_PROPERTY:
			criterion = Restrictions.gtProperty(propertyName, otherPropertyName);
			break;
		case Filter.LE_PROPERTY:
			criterion = Restrictions.leProperty(propertyName, otherPropertyName);
			break;
		case Filter.LT_PROPERTY:
			criterion = Restrictions.ltProperty(propertyName, otherPropertyName);
			break;
		case Filter.IS_EMPTY:
			criterion = Restrictions.isEmpty(propertyName);
			break;
		case Filter.IS_NOT_EMPTY:
			criterion = Restrictions.isNotEmpty(propertyName);
			break;
		case Filter.IS_NULL:
			criterion = Restrictions.isNull(propertyName);
			break;
		case Filter.IS_NOT_NULL:
			criterion = Restrictions.isNotNull(propertyName);
			break;
		case Filter.LIKE:
			criterion = Restrictions.like(propertyName, "%" + value + "%");
			break;
		case Filter.LEFT_LIKE:
			criterion = Restrictions.like(propertyName, "%" + value);
			break;
		case Filter.RIGHT_LIKE:
			criterion = Restrictions.like(propertyName, value + "%");
			break;
		case Filter.IN:
			if (collectionValues == null) {
				criterion = Restrictions.in(propertyName, objectValues);
			} else {
				criterion = Restrictions.in(propertyName, collectionValues);
			}

			break;
		case Filter.BETWEEN:
			criterion = Restrictions.between(propertyName, lowValue, highValue);
			break;
		case Filter.NOT:
			criterion = Restrictions.not(buildCriterion(logicCondition));
			break;
		case Filter.AND:
			criterion = Restrictions.and(buildCriterion(logicCondition), buildCriterion(otherLogicCondition));
			break;
		case Filter.OR:
			criterion = Restrictions.or(buildCriterion(logicCondition), buildCriterion(otherLogicCondition));
			break;
		default:
			criterion = Restrictions.like(propertyName, "%" + value + "%").ignoreCase();
		}
		return criterion;
	}

	private static void addOrder(Criteria criteria, String property, String order) {
		if (order.equals(Sort.ASC)) {
			criteria.addOrder(Order.asc(property));
		} else if (order.equals(Sort.DESC)) {
			criteria.addOrder(Order.desc(property));
		}
	}
}
